package com.terracloud.server.service.entitiy.role;

import com.terracloud.server.common.data.Role;
import com.terracloud.server.common.data.audit.ActionType;
import com.terracloud.server.common.data.exception.ThingsboardErrorCode;
import com.terracloud.server.common.data.exception.ThingsboardException;
import com.terracloud.server.common.data.id.TenantId;
import com.terracloud.server.common.data.page.PageData;
import com.terracloud.server.dao.model.sql.RoleEntity;
import com.terracloud.server.dao.model.sql.UserRoleEntity;
import com.terracloud.server.dao.sql.role.RoleRepository;
import com.terracloud.server.dao.sql.role.UserRoleRepository;
import com.terracloud.server.service.entitiy.AbstractTbEntityService;
import com.terracloud.server.service.security.model.SecurityUser;
import com.terracloud.server.utils.PageDataUtils;
import jakarta.persistence.criteria.Predicate;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;

/**
 *
 * @author chenhainan
 * @since 2025/10/20
 */
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends AbstractTbEntityService implements RoleService {

    private final RoleRepository roleRepository;
    private final UserRoleRepository userRoleRepository;

//    private final Cachc

    @Override
    public PageData<Role> getRoles(TenantId tenantId, int page, int pageSize, String textSearch) {
        Specification<RoleEntity> condition = (root, query, builder) -> {
            List<Predicate> conditions = new ArrayList<>();
            conditions.add(builder.equal(root.get("tenantId"), tenantId.getId()));
            if (StringUtils.hasText(textSearch)) {
                conditions.add(builder.like(root.get("name"), '%' + textSearch + '%'));
            }
            return builder.and(conditions.toArray(new Predicate[0]));
        };
        return PageDataUtils.toPageData(roleRepository.findAll(condition, PageRequest.of(page, pageSize)), RoleEntity::toData);
    }

    @Override
    public Role saveRole(Role role, SecurityUser currentUser) {
        final var actionType = role.getRoleId() == null ? ActionType.ADDED : ActionType.UPDATED;
        role.setTenantId(currentUser.getTenantId());
        final var savedRole = roleRepository.save(new RoleEntity(role)).toData();
        logEntityActionService.logEntityAction(savedRole.getTenantId(), savedRole.getRoleId(), savedRole, actionType, currentUser);
        return savedRole;
    }

    @Override
    public Role getRoleInfo(SecurityUser currentUser, UUID roleId) {
        return roleRepository.findByTenantIdAndId(currentUser.getTenantId().getId(), roleId).toData();
    }

    @Override
    public Role findRoleByName(TenantId tenantId, String roleName) {
        return roleRepository.findByTenantIdAndName(tenantId.getId(), roleName).toData();
    }

    @Override
    public Role findUserRole(UUID userId) throws Throwable {
        final var userRole = userRoleRepository.findByUserId(userId);
        if (userRole == null) {
            return null;
        }
        return roleRepository.findById(userRole.getRoleId())
                .orElseThrow(() -> new ThingsboardException("用户指定的角色未找到", ThingsboardErrorCode.BAD_REQUEST_PARAMS))
                .toData();
    }

    @Override
    @Transactional
    public void deleteRole(SecurityUser currentUser, UUID roleId) throws ThingsboardException {
        if (userRoleRepository.countByRoleId(roleId) > 0) {
            throw new ThingsboardException("角色使用中,无法删除", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
        }
        roleRepository.removeByTenantIdAndId(currentUser.getTenantId().getId(), roleId);
    }
}
